﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace Engine.Attributes
{
	public class AttributeUtilities
	{

		/// <summary>
		/// Collects all properties in obj that are tagged with the attribute T
		/// 
		/// This is adapted from a solution by Konrad Rudolf posted to the stackoverflow.com
		/// question at http://stackoverflow.com/questions/208570/how-do-i-get-the-instance-value-of-a-property-marked-with-a-attribute
		/// </summary>
		/// <typeparam name="T">an attribute type</typeparam>
		/// <param name="obj">the object to inspect</param>
		/// <returns>the names of the relevant properties; null if the indicated attribute is not found</returns>
		public static PropertyInfo[] Collect<T>(object obj)
		{
			Type t = obj.GetType();
			return AttributeUtilities.Collect<T>(t);
		}


		/// <summary>
		/// Collects all properties in the given Type that are tagged with the attribute T
		/// 
		/// This is adapted from a solution by Konrad Rudolf posted to the stackoverflow.com
		/// question at http://stackoverflow.com/questions/208570/how-do-i-get-the-instance-value-of-a-property-marked-with-a-attribute
		/// </summary>
		/// <typeparam name="T">an attribute type</typeparam>
		/// <param name="t">the Type to inspect</param>
		/// <returns>the names of the relevant properties; null if the indicated attribute is not found</returns>
		public static PropertyInfo[] Collect<T>(Type t)
		{
			List<PropertyInfo> inPortProps = new List<PropertyInfo>();
			foreach (PropertyInfo prop in t.GetProperties())
			{
				Object[] attrs = prop.GetCustomAttributes(typeof(T), true);
				if (attrs.Length != 0)
				{
					inPortProps.Add(prop);
				}
			}

			if (inPortProps.Count == 0) return null;

			return inPortProps.ToArray();
		}


		/// <summary>
		/// Collects all the ConfigAttribute properties defined on an object
		/// </summary>
		/// <param name="obj">the object to inspect</param>
		/// <returns>an array of ConfigAttribute properties</returns>
		public static PropertyInfo[] CollectConfigs(object obj)
		{
			return Collect<ConfigAttribute>(obj);
		}

		/// <summary>
		/// Collects all the ConfigAttribute properties defined on a Type
		/// </summary>
		/// <param name="t">the Type to inspect</param>
		/// <returns>an array of ConfigAttribute properties</returns>
		public static PropertyInfo[] CollectConfigs(Type t)
		{
			return Collect<ConfigAttribute>(t);
		}

		/// <summary>
		/// Collects all the InspectableAttribute properties defined on an object
		/// </summary>
		/// <param name="obj">the object to inspect</param>
		/// <returns>an array of InspectableAttribute properties</returns>
		public static PropertyInfo[] CollectInspectables(object obj)
		{
			return Collect<InspectableAttribute>(obj);
		}

		/// <summary>
		/// Collects all the InspectableAttribute properties defined on a Type
		/// </summary>
		/// <param name="t">the Type to inspect</param>
		/// <returns>an array of InspectableAttribute properties</returns>
		public static PropertyInfo[] CollectInspectables(Type t)
		{
			return Collect<InspectableAttribute>(t);
		}
	}
}
